import cv2
import numpy as np
from insightface.app import FaceAnalysis

def is_standard_face(image_path, min_face_size=100, max_angle=15, blur_threshold=60):
    """
    判断一张照片是否是标准人脸
    :param image_path: 图片路径
    :param min_face_size: 最小人脸尺寸（像素）
    :param max_angle: 最大允许偏转角度（yaw/pitch/roll）
    :param blur_threshold: 模糊阈值（Laplacian 方差）
    :return: (bool, reason)  是否标准人脸, 失败原因
    """
    # 1. 加载图像
    img = cv2.imread(image_path)
    if img is None:
        return False, "无法加载图片"

    # 2. 初始化 InsightFace
    app = FaceAnalysis(name="buffalo_l")
    app.prepare(ctx_id=0, det_size=(640,640))

    # 3. 检测人脸
    faces = app.get(img)
    if len(faces) == 0:
        return False, "未检测到人脸"
    if len(faces) > 1:
        return False, "检测到多张人脸"

    face = faces[0]

    # 4. 人脸尺寸检查
    x1, y1, x2, y2 = [int(v) for v in face.bbox]
    w, h = x2 - x1, y2 - y1
    if w < min_face_size or h < min_face_size:
        return False, f"人脸太小 ({w}x{h})"

    # 5. 清晰度检查（Laplacian）
    gray = cv2.cvtColor(img[y1:y2, x1:x2], cv2.COLOR_BGR2GRAY)
    blur_score = cv2.Laplacian(gray, cv2.CV_64F).var()
    if blur_score < blur_threshold:
        return False, f"人脸模糊 (清晰度={blur_score:.2f})"

    # 6. 姿态角度检查
    yaw, pitch, roll = face.pose
    if abs(yaw) > max_angle or abs(pitch) > max_angle or abs(roll) > max_angle:
        return False, f"人脸角度过大 (yaw={yaw:.1f}, pitch={pitch:.1f}, roll={roll:.1f})"

    return True, "标准人脸 ✅"


if __name__ == "__main__":
    img_path = "test.png"  # 替换成你的照片路径
    ok, reason = is_standard_face(img_path)
    print(reason)

    img_path = "f4a832ea23a449449f68fe8fe7618f89.png"  # 替换成你的照片路径
    ok, reason = is_standard_face(img_path)
    print(reason)

    img_path = "download.jpg"  # 替换成你的照片路径
    ok, reason = is_standard_face(img_path)
    print(reason)

    img_path = "2222.jpg"  # 替换成你的照片路径
    ok, reason = is_standard_face(img_path)
    print(reason)

